package top.chengdongqing.weui.core.ui.components.refreshview

import androidx.compose.animation.core.Animatable
import androidx.compose.animation.core.tween
import androidx.compose.foundation.gestures.detectVerticalDragGestures
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.BoxScope
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.offset
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.width
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.input.pointer.pointerInput
import androidx.compose.ui.unit.IntOffset
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import kotlinx.coroutines.launch
import top.chengdongqing.weui.core.ui.components.loading.WeLoading

// 定义刷新阈值，可根据需要调整
private const val REFRESH_THRESHOLD = 100

@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun WeRefreshView(
    modifier: Modifier = Modifier,
    onRefresh: (suspend () -> Unit)? = null,
    content: @Composable BoxScope.() -> Unit
) {
    // 记录是否正在刷新
    var isRefreshing by remember { mutableStateOf(false) }
    // 记录垂直偏移量，使用 Animatable 实现动画效果
    val offsetY = remember { Animatable(0f) }
    // 根据状态获取刷新提示信息
    val refreshingTips = getRefreshingTips(isRefreshing, offsetY.value)
    // 获取一个记住的协程作用域
    val coroutineScope = rememberCoroutineScope()
    LaunchedEffect(isRefreshing) {
        if (isRefreshing) {
            // 开始刷新时执行刷新操作
            onRefresh?.invoke()
            // 刷新完成后，将偏移量动画回到初始位置
            launch {
                offsetY.animateTo(0f, animationSpec = tween(300))
            }
            isRefreshing = false
        }
    }

    Box(
        modifier = modifier
            .fillMaxSize()
            .pointerInput(Unit) {
                detectVerticalDragGestures { change, dragAmount ->
                    if (!isRefreshing) {
                        val newOffset = offsetY.value + dragAmount
                        if (newOffset >= 0) {
                            // 更新偏移量
                            coroutineScope.launch {
                                offsetY.snapTo(newOffset)
                            }
                        }
                        if (change.position.y < 10 && dragAmount > 0) {
                            change.consume()
                        }
                    }
                }
            }
    ) {
        // 刷新提示区域
        Row(
            modifier = Modifier
                .fillMaxWidth()
                .padding(vertical = 20.dp),
            verticalAlignment = Alignment.CenterVertically,
            horizontalArrangement = Arrangement.Center
        ) {
            // 自定义加载动画
            WeLoading(isRotating = isRefreshing)
            Spacer(modifier = Modifier.width(8.dp))
            // 显示刷新提示文本
            Text(
                refreshingTips,
                color = MaterialTheme.colorScheme.onSecondary,
                fontSize = 14.sp
            )
        }

        // 根据偏移量进行内容布局
        Box(
            modifier = Modifier
                .fillMaxSize()
                .offset {
                    IntOffset(x = 0, y = offsetY.value.toInt())
                }
                .pointerInput(Unit) {
                    detectVerticalDragGestures { change, _ ->
                        if (offsetY.value > 0) {
                            if (change.position.y < 10) {
                                change.consume()
                            }
                        }
                    }
                }
        ) {
            content()
        }

        // 当手指抬起时，判断是否触发刷新
        LaunchedEffect(offsetY.value) {
            if (offsetY.value >= REFRESH_THRESHOLD) {
                isRefreshing = true
            } else if (offsetY.value > 0) {
                // 未达到阈值，动画回到初始位置
                launch {
                    offsetY.animateTo(0f, animationSpec = tween(300))
                }
            }
        }
    }
}

private fun getRefreshingTips(isRefreshing: Boolean, offset: Float): String {
    return when {
        isRefreshing -> "刷新中..."
        offset >= REFRESH_THRESHOLD -> "释放立即刷新"
        offset > 0 -> "继续下拉执行刷新"
        else -> ""
    }
}

/*
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun WeRefreshView(
    modifier: Modifier = Modifier,
    onRefresh: (suspend () -> Unit)? = null,
    content: @Composable BoxScope.() -> Unit
) {
    val refreshState = rememberPullToRefreshState()
    val refreshingTips = getRefreshingTips(refreshState, refreshState.positionalThreshold)

    LaunchedEffect(refreshState) {
        snapshotFlow { refreshState.isRefreshing }.filter { it }.collect {
            onRefresh?.invoke()
            refreshState.endRefresh()
        }
    }

    Box(
        modifier = modifier
            .fillMaxSize()
            .nestedScroll(refreshState.nestedScrollConnection)
    ) {
        // 刷新的标识
        Row(
            modifier = Modifier
                .fillMaxWidth()
                .padding(vertical = 20.dp),
            verticalAlignment = Alignment.CenterVertically,
            horizontalArrangement = Arrangement.Center
        ) {
            WeLoading(isRotating = refreshState.isRefreshing)
            Spacer(modifier = Modifier.width(8.dp))
            Text(
                refreshingTips,
                color = MaterialTheme.colorScheme.onSecondary,
                fontSize = 14.sp
            )
        }

        val animatedRefreshOffsetY by animateIntAsState(
            targetValue = refreshState.verticalOffset.toInt(),
            label = "ScrollViewRefreshOffsetYAnimation"
        )
        Box(
            modifier = Modifier
                .matchParentSize()
                .offset {
                    IntOffset(x = 0, y = animatedRefreshOffsetY)
                }
        ) {
            content()
        }
    }
}

@OptIn(ExperimentalMaterial3Api::class)
private fun getRefreshingTips(state: PullToRefreshState, positionalThresholdPx: Float): String {
    return when {
        state.isRefreshing -> "刷新中..."
        state.verticalOffset > positionalThresholdPx -> "释放立即刷新"
        state.verticalOffset > 0 -> "继续下拉执行刷新"
        else -> "刷新中..."
    }
}*/
